/*
 * @Author: Wangjun
 * @Date: 2023-03-23 15:50:31
 * @LastEditTime: 2023-06-13 10:40:32
 * @LastEditors: Wangjun
 * @Description:
 * @FilePath: \xrexportd:\go\src\gitee.com\haodreams\libs\itemx\items.go
 * hnxr
 */
package itemx

import (
	"fmt"
	"sort"
	"strings"
)

// 基础数据
type BasicInfo struct {
	ID           int
	CompanyID    int
	PlantID      int
	ModelID      int
	ExtendColumn map[string]*float64 //扩展列数据
	pos          int                 //字段个数+1
	ExtendKey    []string
}

// 一个测点的完整信息
type Items struct {
	BasicInfo
	Interval  int //数据间隔
	tsName    string
	Desc      string         //描述
	mapFiled  map[string]int //简码
	Columns   []string
	insertSQL string //insert sql  语句
	createSQL string
	vals      [][]any
	array     []*Item
}

// ck 插入的sql
func (m *Items) InsertSQL() string {
	return m.insertSQL
}

// ck 建表的sql
func (m *Items) CreateSQL() string {
	return m.createSQL
}

/**
 * @description: 获取指定列名的索引
 * @param {string} name
 * @return {*}
 */
func (m *Items) GetIndex(name string) int {
	idx, ok := m.mapFiled[name]
	if ok {
		return idx
	}
	return -1
}

/**
 * @description: 获取指定的行
 * @param {int} idx 行号
 * @return {*}
 */
func (m *Items) GetItem(idx int) *Item {
	if idx < len(m.array) {
		return m.array[idx]
	}
	return nil
}

/**
 * @description:
 * @param {int} size 最大缓存数量 一天是86400
 * @param {*} tableName 写入的表名
 * @param {string} tsName 时间戳名称 ，默认是ts
 * @param {[]string} fileds //列名
 * @param {map[string]float} 扩展列数据信息
 * @return {*}
 */
func NewItems(interval int, tableName string, fileds []string, extendColumn map[string]*float64, tsName ...string) *Items {
	m := new(Items)
	m.pos = 5 + len(extendColumn) //BasicInfo 全局字段 + creat_time 的个数
	//is.sql = sql
	if len(tsName) > 0 && tsName[0] != "" {
		m.tsName = tsName[0]
	} else {
		m.tsName = "ts"
	}

	m.Columns = fileds

	if interval == 0 {
		interval = 5
	}
	if interval > 3600 {
		interval = 3600
	}

	size := 86400 / interval
	m.Interval = interval

	wh := strings.Repeat("?,", len(fileds)+m.pos)
	wh = wh[:len(wh)-1]
	cols := ""
	ecs := make([]string, 0, len(extendColumn))

	for key := range extendColumn {
		ecs = append(ecs, key)
	}
	sort.Strings(ecs)

	m.ExtendKey = ecs
	m.ExtendColumn = extendColumn

	ecs = append(ecs, fileds...)
	cols += strings.Join(ecs, ",")
	cols = strings.ToLower(cols)

	m.insertSQL = fmt.Sprintf("INSERT INTO %s (%s, id, company_id, plant_id, model_id, %s) VALUES (%s);", tableName, m.tsName, cols, wh)

	cols = strings.ReplaceAll(cols, ",", " Decimal(18,2),")
	cols += " Decimal(18,2)"
	m.createSQL = fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s DateTime, id Int32, company_id Int32 DEFAULT 0, plant_id Int32, model_id Int32, write_time DateTime DEFAULT now(), %s) ENGINE = ReplacingMergeTree PARTITION BY toYYYYMMDD(%s) PRIMARY KEY (%s, id) ORDER BY (%s, id) TTL %s + toIntervalMonth(24) SETTINGS index_granularity = 8192",
		tableName, m.tsName, cols, m.tsName, m.tsName, m.tsName, m.tsName)
	m.mapFiled = map[string]int{}
	for i, filed := range fileds {
		m.mapFiled[filed] = i
	}
	m.vals = make([][]any, size)
	m.array = make([]*Item, size)
	for i := range m.array {
		m.array[i] = NewItem(&m.BasicInfo, len(fileds))
	}
	return m
}

/**
 * @description: 转化符合条件的数组
 * @return {*}
 */
func (m *Items) ToArray() [][]any {
	i := 0
	for _, item := range m.array {
		if item.updated {
			m.vals[i] = item.Vals
			i++
		}
	}
	return m.vals[:i]
}

/**
 * @description: 代码复用， 出现新的测点
 * @return {*}
 */
func (m *Items) Reset() {
	for _, item := range m.array {
		item.Reset()
	}
}

// Item 对应数据的行
type Item struct {
	updated bool //数据是否更新过
	*BasicInfo
	Ts   int64 //timestamp
	vals []float64
	Vals []any
}

// 行的复用，数据初始化
func (m *Item) Reset() {
	m.updated = false
	n := len(m.vals)
	for i := 0; i < n; i++ {
		m.vals[i] = -9999
	}
}

func (m *Item) Updated() bool {
	return m.updated
}

// 对指定的列赋值
func (m *Item) SetValue(idx int, v float64) {
	m.vals[idx] = v
	m.updated = true
}

/**
 * @description: 获取float value
 * @return {*}
 */
func (m *Item) FloatValues() []float64 {
	return m.vals
}

// 新建一行
func NewItem(bi *BasicInfo, n int) *Item {
	m := new(Item)
	m.BasicInfo = bi
	m.vals = make([]float64, n)
	n += m.pos
	m.Vals = make([]any, n)

	m.Vals[0] = &m.Ts
	m.Vals[1] = &m.ID
	m.Vals[2] = &m.CompanyID
	m.Vals[3] = &m.PlantID
	m.Vals[4] = &m.ModelID

	for i, key := range m.ExtendKey {
		m.Vals[5+i] = m.ExtendColumn[key]
	}
	for i := m.pos; i < n; i++ {
		pos := i - m.pos
		m.vals[pos] = -9999
		m.Vals[i] = &m.vals[pos]
	}
	return m
}
